Paoe 21. Special Purpose Commands Set Orlqln. Assemble. Run Program. Set Parameters. Set Or!-gin Onnn Set the origin for the assembled program to nnn. D Set the oriain for the assembled proaram to the first free byte after the source file. This command causes the Editor Assembler to set the oriain automatically and is therefore ideal for beginners in all respects. If a program is assembled here then it can be run with the editor assembler still in memory. Provided your proaram does not alter any memory below that set by the Origin command then you may iump back to the Editor Assembler at 31488 (7BOOH) and your source file will be intact. This is done by havina the iump command as the final command in your program, either in the last program line in simple programs or as part of a conditional loop to enable exit from more complex programs. Assembl& A Assemble program, I.e. write an object program from the source program. The program will be assembled starting from the first free byte after the source file but It will be assembled in reference to the value set by the Origin command, which is the address that the program will load and execute at when it Is loaded back Into the VZ200 or VZ300 as an object tape. N.B. The Origin should be set before a program is assembled (see Set Origin command). Page 22. Run R Run the assembled program. The program must be correctly assembled before it can be Run. To do this two requirements must be met. If any lines have been edited, deleted. or Inserted since assembly you will receive a REASSEMBLY REQUIRED error. If the Origin is not set to the first free byte after the source code using the O command you will get a WRONG ORIGIN FOR RUN error, i.e. the program cannot be run from the Editor Assembler unless the Origin is set to the first free byte after the source code. Remember that the first free byte after the source code Is constantly changing as you enter source lines so if you wish to test run your programs using the Run command use the O command before every assembly. You will be prompted SURE (Y-N) if everything is correct to run the Proqram. Assuming that you are sure you are ready to run the program you should run It by pressing Y. **** WARNING **** Always save your source file before test running a program in memory because often the slightest mistake will cause a program crash which will result in one of two things; either the computer will become locked up and you will have to turn it off and on again to gain control or the computer will reset itself. In either case all that was in memory will have been lost and you will have to load the Editor Assembler again and then your saved source file. If you have not saved the source file you will have,to type It all In again. If you have not made provision In your source code for a return to the Editor Assembler on completion of the program Run the program will probably default to BASIC on conclusion of the run. The Editor Assembler and program will then have to be reloaded (the source code will have to be re-entered from the keyboard If It was not saved). Therefore if the program Is to be test Run provision must be made for a return to the Editor Assembler before assembly of the program. Provided your program does not alter any memory below that set by the Origin command this can be done by including an instruction to jump to 31488 (7BOOH) as the final command in your program, either In the last program line in simple programs or as part of a conditional loop to enable exit from more complex programs. Page 23. Set Parameters The parameters are used to set certain assembly and listing options i.e. N = Message format. I - ASC11 2 - screen characters white on black background. 3 - screen characters black on white background. A = List all lines (A On) or only lines with errors (A Off). B = Halt list at each error (B On) or no halt (B Off). C = List to printer and screen (C On) or screen only (C Off). N.B. Some versions of the EdAssm do not List to printer as intended but there are several "patches" available to make the printer operate. The best source of information on these would be your user group. S Set parameters to default value. The default values for the parameters are N I A Off B Off SNABC Set parameter to the number given (1-3) and turn A, B, and C on. Not a)) four parameters need be given when this command is used but any parameter not specified will automatically be reset to Its default value. For full details regarding parameters etc. see section on massembly and Listing Options". Page 24. SUMMARY of COMMANDS Edit comands Insert I Innn Edit E Ennn Ennn:mmm Delete D Dnnn Dnnn:mmm D* List L Lnnn Lnnn:- L-:nnn Lnnn:mmm L* Cursor Up (. Cursor Down () = slow listing down. = speed listing up. = hold listing. = continue listing after a hold. (i.e. - ) exit the list mode. Find Fstring Exit Edit mode (i.e. - ) Tape comandg Tape Save TSname Tape Load TL Tape Verify TV Tape Merge TM Tape Object TO Special Purpose commands Set Origin Onnn O Assemble A Run R Set Parameters S SNABC Page 25. OPCODES RECOGNISED BY THIS ASSEMBLER The following list gives the Opcode and a typical Operand followed by a brief description of the operation performed. Only those Opcodes are given which are relevant to the VZ Editor Assembler, however this does seem to be a comprehensive list of ZBO Opcodes. It would be impractical to list every possible Operand therefore representative examples showing the general patterns of the Operands that can be used with each Opcode have been given and it is hoped that these together with the explanations may provide others with an easier introduction to Assembly Language programming than the writer had. Program Control Operationa CALL nn Call address nn, i.e. go to the sub-routine starting at address nn and follow its instructions. CALL *,nn Conditional Call. The call to the sub-routine at address nn will only be performed if the nominated condition '*' is met. RET Unconditional Return. RET Conditional Return.. i.e. returns only if the nominated condition ,'*,' is met. jp nn Jump to memory location nn. jp (HL) Jump to the memory location indicated by the contents of the HL memory pair. jp *.nn Jump to the memory location nn if the nominated condition '*' is met. jp *,(HL) Jump to the memory location indicated by the contents of the HL memory pair if the nominated condition '*' is met. JR Label Unconditional Jump to the location indicated by the Label. [Numeric value of relative iumps does not have to be calculated in Assembly Language programming). JR *,Label Conditional Jump to the location Indicated by the Label, i.e. .,iumps to the labelled program line only if the nominated condition '*' is met. [Numeric value of relative iumps does not have to be calculated in Assembly Language programming). Page 26. DJNZ Label Conditional Jump to the location Indicated by the Label. -IFIrst the contents of register B is decremented. If the result is Not Zero a iump to the program line indicated by the Label will take place. If the result is Zero the jump will not occur and the next instruction will be executed. [The numeric value of the ,jump does not have to be calculated in Assembly Language programming). RST nn Restart at paae zero location nn. NOP No Operation. Only the program counter advances. (Sometimes used to aenerate short time delays]. HALT The microprocessor stops operation except for the execution of NOP's to maintain proper memory refresh activity. This is used at the termination of a program or when waiting for an interrupt to occur, i.e. an interrupt is required to restart after a Halt instruction. Conditions c Carry. Do It if Carry flag Is Set, I.e. If C I NC Non-Carry. Do It If Carry flag Is Reset, i.e. if C = 0 m Sign Negative. Do it if Sign flag Is negative, i.e. If S = 0 p Sign Positive. Do it If Sign flag is positive, i.e. if S = I PE Parity Even. Do it If Parity Is Even, I.e. if P/V I PO Parity Odd. Do it If Parity is Odd, I.e. If P/V 0 z Zero. Do It If Zero flag is Set (Zero condition), I.e. if Z I NZ Non-Zero. Do it if Zero flag Is Reset (Non-Zero condition), I.e. if Z 0 Paoe 27. Data Transfer Operations Note that the general pattern of the operand is as follows First part. i.e. before comma = Load TO. i.e. the value here will be changed by the operation. Second oart, i.e. after comma = Load FROM, i.e. the value here will not be chanced by the operation. Brackets enclose a memory address or a register whose contents speclfv a memory address. LD A,nn Load the Accumulator Direct with one byte of data, nn. LD BC.nn Load resister pair BC Direct with two bvtes of data. nn. LD A.B Load the Accumulator with the contents of resister B. LD C..A Load resister C with the contents of the Accumulator. LD A,(BC) Load the Accumulator with the contents of the memory location pointed to by register pair BC. LD (BC).A Load the Address pointed to by resister pair BC with the contents of the Accumulator. LD A.(nn) Load the Accumulator with the contents of memory location nn. LD (nn),A Load memory location nn with the contents of the Accumulator. LD (nn),.BC Load memory locations nn and nn+l with the contents of resister pair BC. The contents of C are loaded into the nominated address and the contents of B into the next address. IN A.(n) Data from the input port In' is loaded into the Accumulator. IN B.(C) Data from the input port specified by the contents of resister C is loaded into resister B. OUT n.A The contents of the Accumulator are output to Port 'n'. OUT (C),B The contents of resister B are cutout to the Part specified by register C. EX DE.HL Exchange the contents of DE and HL registers. EX AF.AF, Exchange the contents of the Accumulator and Flao resister with the contents of the Alternate Accumulator and Flag register. Page 28. EX (SP),HL Exchange the contents of the memory location addressed by the Stack Pointer with the contents of the L register, and the contents of the next address, i.e. SP+I, with the contents of the H register. EXX Exchange the contents of the general purpose registers with the contents of the corresponding alternate registers. PUSH C Place the byte from register C onto the stack (at the addres5 of the pointer less one). PUSH HL Place the two bytes from register pair HL onto the stack. The contents of the High Order register are stored in the stack at the address of the pointer less one and the contents of the Low Order register are stored at the address of the stack pointer less two. POP c Remove one byte from the stack and load It into C register. POP AF Remove two bytes from the stack. The first byte is loaded into F and the second into A. Block Data Transfer & Search Operations LDD The contents of the memory location Indicated by the contents of the HL register pair is transferred to the location pointed to by the contents of the DE register pair. After the data has been transferred both HL and DE are decremented by one. The 'counter-register" pair BC Is also decremented by one. LDDR This Is the same as LDD except that the Instruction will be repeated until the value In the Ocounter-register" pair BC ooes to zero. LDI This is the same as LDD except that the HL and DE pairs are lncremented by a count of one instead of being decremented. The "counter-register" pair BC is still decremented. LDIR This Is the same as LDI except that the Instruction will be repeated until the value In the "counter-register" pair BC goes to zero. I CPD The contents of the memory location indicated by the HL register pair Is subtracted from the accumulator and the result discarded. Both HL and BC are decremented. CPDR This is the same as CPD except that It is repeated until either BC = 0 or A = HL. Page 29. CPI The contents of the memory location indicated by the HL register pair Is compared with the Accumulator. HL is then lncremented and BC decremented. CPIR This is the same as CPI except that It is repeated until either BC 0 or A = HL. Input/Output Ooerat gna IND Input from a port specified by the contents of register C. One byte of data Is transferred to the memory location addressed by the contents of the HL register pair. The values in registers B and HL will be decremented at the end of this instruction. INDR This Is the same as IND except that It is repeated until register B = 0. INI This Is the same as IND except that the HL register contents Is decremented Instead of lncremented at the end of the Instruction. INIR This 15 the same as IN] except that It Is repeated until register B = 0. OUTD Outputs data from the memory location specified by the contents of the HL register pair to the port specified by the contents of register C. The contents of the B register and of the HL register pair will both be decremented. OTDR As for OUTD except that the process Is repeated until B = 0. OUTI Outputs data from the memory location specified by the contents of the HL register pair to the port specified by the contents of register C. The contents of the B register will be decremented but the contents of the HL register pair will be incremented. OTIR As for OUTI except that the process is repeated until B = 0. Page 30. Arithmetic & Logic Operations Note that the aeneral pattern of the operand Is as follows First part, I.e. before comma = operation TO, i.e. the value here will be chanced by the operation. Second part, i.e. after coma = operation FROM, i.e. the value here will not be chanced by the operation. Brackets enclose a memory address or a resister whose contents specify a memory address. ADD A,nn Add the value nn to the Accumulator. ADD A,B Add the value in the B register to the Accumulator. ADD HL,BC Add the value in the BC register pair to the HL register pair. ADD IX..BC Add the value in the BC register pair to the Index register. ADD A.(nn) Add the value of the byte stored at address nn to the A resister ADC A,nn Add with carry the value nn to the Accumulator. ADC A.B Add with Carry the value in the B register to the Accumulator. ADC HL,BC Add with Carry the value in the BC register pair to the HL register pair. ADC A,(nn) Add with Carry the value of the byte stored at address nn to the A register. SUB nn Subtract the value nn from the Accumulator. SUB B Subtract the value In the nominated register from the Accumulator. SUB (HL) Subtract the value In the memory location pointed to by the HL register pair from the Accumulator. SBC nn Subtract the value nn and the Carry Flag from the Accumulator (subtract with carry). SBC A,B Subtract the value in the nominated register and the Carry Flag from the Accumulator (subtract with carry). SBC A,(HL) Subtract the value in the memory location pointed to by the HL register pair and the Cary Flag from the Accumulator (subtract with carry). SCF Set Carry Flag, i.e. C = I CCF Complement Carry Flag, I.e. reverse (or invert) the condition of the Carry flag. Paoe 31 CPL Complement Accumulator. i.e. chance all I's to O's and all O's to I's. NEG Two's complement the Accumulator, i.e. chance all I's to O's and all O's to I's then add I to the result. (i.e. Chanae the sion of the number in the Accumulator). CP A Compare the Accumulator with itself. CP B Compare the value in the B register with the value in the Accumulator. CP (nn) Compare the value in address nn with the value In the accumulator. DAA Decimal Ad.iust Accumulator. Produces one diolt for the four least significant bits and one for the four most significant bits. The carry flao is set to I if an overflow occurs. INC B The contents of the nominated resister is incremented by 1. INC HL The contents of the nominated resister pair is incremented bv 1. INC (HL) The contents of the memorv location pointed to by the nominated register pair is incremented by 1. DEC B The contents of the nominated resister is clecremented bv 1. DEC HL The contents of the nominated resister pair is decremented bv 1. DEC (HL) The contents of the memory location Pointed to by the nominated resister Pair is decremented by 1. AND A Logic AND the Accumulator with itself. AND B Looic AND the nominated resister with the Accumulator. AND (nn) Looic AND the byte at the address nn with the Accumulator. AND nn Loqic AND the data nn with the Accumulator. OR A Loqic OR the Accumulator with itself. OR B Logic OR the nominated register with the Accumulator. OR (nn) Logic OR the byte at the address nn with the Accumulator. OR nn Logic OR the data nn with the Accumulator. XOR A Exclusive OR the Accumulator with itself. XOR B Exclusive OR the nominated register with the Accumulator. XOR (nn) Exclusive OR the byte at the address nn with the Accumulator. XOR nn Exclusive OR the data nn with the Accumulator. Page 32. Rotate and Shift Ove[ations RL n Rotate operand n Left through Carry (9 bit shift) RR Rotate operand n Right through Carry (9 bit shift) RLA Rotate Accumulator Left through Carry RRA Rotate Accumulator Right through Carry RLC r Rotate register r Left with branch Carry (B bit shift) RRC r Rotate register r Right with branch Carry (O bit shift) RLCA Rotate Accumulator Left with branch Carry (B bit shift) RRCA Rotate Accumulator Right with branch Carry (8 bit shift) RLD Rotate Left Decimal RRD Rotate Right Decimal SLA Arithmetic Shift Left SRA Arithmetic Shift Right SRL Logical Shift Right Bit Og)erations BIT n,A Bit test. If bit n of the A register is 'O' the Zero Flag is set to '1'. BIT n,(nn) Bit test. If bit n of the byte at address nn Is '1' the Zero Flag is set to 101. SET n,F Set Bit 'n' In the specified register to the logic One condition. SET n,(F) Set Bit 'n' In the memory location Indicated by the specified register to the logic One condition. RES n,(C) Reset Bit 'n' in the specified register to the logic Zero condition. Page 33. Stack and Stack Pointer Operations LD SP.rr Load the Stack Pointer from the nominated register. EX (SP),HL Exchange HL with top of stack, i.e. exchange the contents of the memory location addressed by the Stack Pointer with the contents of the L register. and the contents of the next address. i.e. SP+I, with the contents of the H register. EX (SP),IX Exchange IX with too of stack. EX (SP).]Y Exchange IY with top of stack. PUSH C Place the byte from resister C onto the stack (at the address of the pointer less one). PUSH HL Place the two bytes from resister pair HL onto the stack. The contents of the High Order register are stored in the stack at the address of the Pointer less one and the contents of the Low Order resister are stored at the address of the stack pointer less two. PUSH rr Push contents of register pair rr onto the stack. PUSH IX Push contents of the IX register onto the stack. PUSH IY Push contents of the IY register onto the stack. POP c Remove one byte from the stack and load it into C register. POP AF Remove two bytes from the stack. The first byte is loaded into F and the second into A. POP rr Pop to register pair rr from the stack. POP ix Pop to register IX from the stack. POP IY Pop to resister IY from the stack. Interrupt and Machine Control Operations El Enable the maskable Interrupt. im n Set Interrupt Mode to n. (n = 0. 1, or 2). DI Disable a maskable interrupt signal. RST nn Restart at paoe zero location nn. RETN Return from a non-maskable interrupt. Page 34. RETI Return from Interrupt. NOP No Operation. Only the program counter advances. [Smetimes used to generate short time delays). HALT The microprocessor stops operation except for the execution of NOP's to maintain proper memory refresh activity. This Is used at the termination of a program or when waiting for an Interrupt to occur '. I.e. an interrupt Is required to restart after a Halt instruction. LD 1,A Load the Interrupt vector register with the contents of the Accumulator. LD A,l Load the Accumulator with the contents of the Interrupt vector resister. LD R,A Load the Memory Refresh register with the contents of the accumulator. LD A,R Load the Accumulator with the contents of the Memory Refresh register. Pseudo-Operations EQU Equates a label to another label or a numeric value. DEFB Defines constants and variables In the program. The araument for DEFB Is a numeric or symbolic expression that can be resolved In eight bits. DEFW Defines constants and variables In the program. The arc_rument for DEFW is a numeric or symbolic expression that can be resolved in sixteen bits. DEFS Reserves a number of bytes in memory without actually filling it with meaningful data, e.g. for allocation of I/O buffers and workina storage areas. N.B. Pseudo-Operations are not Opcodes that are recoanised by the microprocessor; they are additional opcodes which alve instructions to the assembler. Pace 35. Summary of Opcodos and Types of Operations, ADC Arithmetic & Logic LD] Block Data Transfer & Search ADD Arithmetic & Logic LOIR Block Data Transfer & Search AND Arithmetic & Logic NEG Arithmetic & Logic BIT Bit NOP Program Control CALL Program Control Interrupt & Machine Control CCF Arithmetic & Logic OR Arithmetic & Looic CP Arithmetic & Logic OTDR Input/Output CPD Block Data Transfer & Search OTIR Input/Output CPDR Block Data Transfer & Search OUT Data Transfer CPI Block Data Transfer & Search OUTD Input/OutDut CPIR Block Data Transfer & Search OUTI Input/Output CPL Arithmetic & Logic POP Data Transfer DAA Arithmetic & Logic Stack & Stack Pointer DEC Arithmetic & Logic PUSH Data Transfer DEFB Pseudo-OperatiOD Stack & Stack Pointer DEFS Pseudo-Operation RES Bit DEFW Pseudo-OperatiOD RET Program Control DI Interrupt & Machine Control RETI Interrupt & Machine Control DJNZ Program Control RETN Interrupt & Machine Control EI Interrupt & Machine Control RL Rotate & Shift EQU Pseudo-Operation RLA Rotate & Shift E)< Data Transfer RLC Rotate & Shift Stack & Stack Pointer RLCA Rotate & Shift EXX Data Transfer RLD Rotate & Shift HALT Program Control RR Rotate & Shift Interrupt & Machine Control RRA Rotate & Shift im Interrupt & Machine Control RRC Rotate & Shift IN Data Transfer RRCA Rotate & Shift INC Arithmetic & Logic RRD Rotate & Shift IND Input/Output RST Program Control INDR Input/Output Interrupt & Machine Control INI Input/Output SBC Arithmetic & Logic INIR Input/Output SCF Arithmetic & Logic jp Program Control SET Bit JR Program Control SLA Rotate & Shift LD Data Transfer SRA Rotate & Shift Stack & Stack Pointer SRL Rotate & Shift Interrupt & Machine Control SUB Arithmetic & Logic LDD Block Data Transfer & Search XOR Arithmetic & Logic LDDR Block Data Transfer & Search Page .36. Starter Programs, First Load the Editor Assembler Into VZ. If you load from the beginning of the tape you will first see a message detailing the new commands that have been included in the Editor Assembler. Allow the tape to keep loading until you see the message identifying the Editor Assembler Itself and the COMMAND prompt at the bottom of the screen. Program No. 1. This program will 1. Clear the screen by calling a 5ub-routine resident In the VZ 200/300. 2. Provide for a Return to the Editor Assembler after a program Run. 3. Provide a Time Delay for display to the screen so that it remains long enough to be visible. Enter I This is the Insert Command that allows you to enter the Edit mode to write a program. The first line number (001) should now appear on the screen. Enter ;TEST This is a Comment Line. It Is good practice to use Comment lines frequently even though they are not actually used in the program, as a well documented program Is much easier to understand when you return to It at a later date. Also, by making the first line a comment line we make It easier to insert new lines ahead of the first actual program line later If we want to. [The Editor Assembler does not allow new lines to be Inserted ahead of line 1.) Enter CALLIC9H This Is a Call to the clear screen routine that Is resident in the-VZ BASIC at address lC9H, i.e. hexadecimal IC9 (decimal 441). We are starting with this so that we can have the screen clear to see the results of the programs we write. Enter JP31488 This Is a Jump back to the Editor Assembler program to avoid the delay caused by re-loading the program when a Run defaults back to BASIC. The decimal address has been used here, but the hex. address 7BOOH will do exactly the same iob. Enter - [often referred to as l This is the VZ BREAK command, but In the Editor Assembler it is used to exit the Edit mode. You should now be back in the Command mode, as indicated by the COMMAND prompt at the bottom of the screen. Page 37. The Program as it stands will simply clear the screen and then return to the Editor Assembler. To test this we must first set the Origin to the first free space after the source code, then Assemble the program, and finally Run it. Let's try it. Enter D N.B. This is the letter 0 for Origin. If you enter zero Instead you will be advised that You have entered an ILLEGAL COMMAND. When this happens simply re-enter the correct command at the prompt. Enter A During program assembly you will first see PASS # I on assembly of the Opcodes etc., then PASS # 2 when the iumps are checked. Any errors in your proarams will be located during assembly and must be corrected before the program will Run. When the assembler has completed both passes and given a zero error message the program is ready to Run. Enter R You will be prompted SURE (Y-N). As the Origin was set to the first free byte after the source code and the program includes a iump back to the Editor Assembler we can safely Run it, therefore:- Enter Y The screen will be cleared. but the Editor Assembler returns so ouicklv that you will not have noticed the clearina of the Status Line (Top line in inverse characters across the screen). You will also see COMMAND Y at the bottom of the screen. This is probably there because the program ran so quickly that you still had your finger on the Y key when the Editor Assembler returned after the program run was complete. You can use the normal VZ "Rubout" function to remove the Y or simply press return to get a new COMMAND prompt. (The Y will be reported as an ILLEGAL COMMAND but this doesn't matter as you are automatically prompted for another command). As you have seen, things happen very quickly In assembly languge programming so before we start doing anything else let's slow it down a little so that we can see what's happening. For this we need a Delay routine. At the moment we only need 1 t once, but a rout 1 ne I I ke th 1 s cou I d be used I n severa I p I aces 1 n a I ong program so we will start by giving it a Label. This must be from one to four characters long, and to make things easy it should be something that is easily related to the function of the routine, so let's call this one DLY. (If we use other delay routines In the same program we could easily call them DLYI. DLY2, etc.). The NOP instruction can be used for brief pauses in program execution, as when the computer needs time to sort something out, but such a brief pause as is caused by even a hundred NOP's would never be noticed by a human being so a delay loop must be set up. However not only must it be set up, but it must also have an exit. or the delay will be forever. or until the computer is turned off. whichever comes first. In the Z80 microprocessor the DJNZ function is ideal for setting up time delays. (Ref. description of DJNZ under uprogram Control Operations" to see how it works). Page 38. Before progressing any further let's see If our original program is still present. (It certainly should be, If it was entered as above). Enter L You should see this COMMAND L 001 ;TEST 002 CALL IC9H 003 JP 31488 COMMAND (flashing cursor) Now Enter I2 We could have entered 1002 but in practice the non-significant zeros in the line number are not needed, so why bother typing them. We are now Insertina after line 2, before what was originally line 3. Note however that the oriainal line 3 is now line 4 because of the automatic re-numt)erina carried out by the Editor Assembler each time a new line is inserted. The prompt is now at the new line 003. Enter LDB.O [Enter a zero this time, not a letter) The assembler should move on to the next line when you press Return. Enter DLYDJNZDLY The Assembler again moves all the following lines down one to enable you to insert another new line, but for the moment let's pause and try the revised program to see what happens at this stage. Enter - (i.e. ] The Break takes us back to the command mode, and as you did not actually enter anything Into the last new line offered it is ignored, as you will see if you List your program again (by using L). In these new program lines we have set the B register to zero so that when it Is decremented the first time it will go to 255. Because the DJNZ checks for condition AFTER the B register Is decremented It does not find the Zero condition It needs to allow the next step In the program to be carried out. Instead it loops to the Label DLY, In this case from the end of the DJNZ Instruction back to the beginning of it. Because this Is a backwards loop It will keep doing this until the B register returns to zero again. Only then will the DJNZ allow the program to move on to the next line. Now set the Origin and Assemble the program again, and, if It assembles without errors, Run It. There should still be no noticeable difference. The screen clears, but the Editor Assembler still returns far too quickly for an entirely blank screen to be seen, and our " Y" response st I I I appears af-ter the COMMAND prompt. We have Inserted a delay that Is long in computer terms, but still very short in human terms so we will have to somehow Increase the time delay to make it visible. Page 39. If you wish to see more clearly what you are doing List your program again before making the following additions. Enter I3 Enter LDC,O Enter - (i.e. l This new line has loaded a value of zero into the C register to set it also to zero. We then exited the Edit mode because we don't want to insert anything else before the DJNZ instruction at this stage. Enter L Let's List it all aqain to make sure we get our numbers right. We want to insert some lines after the DJNZ instruction now. Enter I5 Enter DECC Enter JRNZ,DLY Enter - In the two program lines just entered we are decrementing register C and then causing the program to jump to DLY if it does not find a Zero condition. Only when the Zero condition occurs will the program go on to the next line. The program will keep returning to the DJNZ loop and repeating it until the JR NZ line finds a Zero condition. Now set the Origin, Assemble, and Run the program again. This time the screen should briefly become completely clear, and the "Y" response to the SURE prompt should no longer appear after the COMMAND prompt when the program returns control of the computer to the Editor Assembler. Let's now see if we can add another loop to extend the delay time even further. By now you should be getting familiar with the actual entry procedure so I'll just tell you what to do and leave you to work out the actual keyboard entries. After line 4 Insert a line which will set the D register to zero. After line ? (the line that now contains the JR NZ,DLY Instruction related to the DEC C) Insert two lines that will Decrement register D and cause the program then to loop back to the DLY label until a Zero condition Is found. When you have done this List your program again to make sure it really says what you thought it should, and in the right places. If you are satisfied that It Is correct then set the Origin, Assemble, and Run the new version of the program. You should find that the screen clears and stays clear for approximately two minutes before control Is returned to the Editor Assembler If you have written the program correctly, so wait patiently or take the opportunity of getting a quick drink while nothing seems to be happening. Page 40. Now here Is a question for you? Why couldn't we have just used two or more DJNZ loops to achieve the extra time delay instead of going to the trouble of setting up other registers to do effectively the same thing? e.g. LD C,O DLY DJNZ DLY DJNZ DLY WARNING Save the "correct" program to tape first if you are going to try to find the answer to this question by entering and runnina the example program given above. If you try this routine instead of using the extra registers and the JR NZ instructions you will find that the screen clears but control is never returned to the Editor Assembler, and the only way to regain control of the computer is tc switch it off and start all over again. Why is this? If you think carefully about what the DJNZ instruction does you should soon recognise the problem. Need a clue? It causes an "infinite loop", but why? Just to make sure that we are still together, your program now should look like this 001 ;TEST 002 Call iC9H 003 LD B,O 004 LD C,C 005 LD D,D 006 DLY DJNZ DLY 007 DEC C 008 JR NZ,DLY 009 DEC D 010 JR NZ,DLY Oil JP 31488 It could be useful to add some labels now to lines 2 and 3 [use the Edit command to do this]. These will make our program easier to follow, but more importantly, the labels can be called from other parts of the program later If required (with some modification to this part to provide for a return to the correct part of the program on completion of the sub-routine called). Thus, although we are not ready to actually use them yet we can start from the begining to form a habit of thinking in terms of program routines and sub-routines. Remember also that the correct way to make a program easy to follow is by using Comment lines (e.g. line 1) but as these do Involve extra typing and these first programs are very simple it has seemed expedient to leave them out for the time being. Labels do make a program easier to followm but this is NOT their purpose. Their purpose Is to provide a unique Identifier for a particular part of the program so that this part can be found when it is needed, and as often as It is needed. Page 41. We will not write the full sub-routines yet, but let's insert labels in lines 2 and 3 to mark the begining of program sections that could be developed into useful sub-routines. On line 2 add the label CLS, for "Clear Screen", and on line 3 add the label DLI to mark the beginning of the delay subroutine. If you have successfully Edited these lines your program should now look like this:- 001 ;TEST 002 CLS Call IC9H 003 DLI LD B,O 004 LD C.0 005 LD D .0 006 DLY DJNZ DLY 007 DEC C 008 JR NZ.DLY 009 DEC D 010 JR NZ,DLY Oil JP 31488 Now let's return to the program itself. We will concede to the experts that there are probably much better and more efficient delay routines. but for beginners this does the trick. The only extra requirement now is to make the delay shorter to avoid unnecessary waiting to return to the Editor Assembler after a program is Run. This can be done by altering the initial value to which one of the registers was set. (More than one of the values could be changed but it is easier to work with one at a time.] Remembering that setting the register to zero actually gives a count of 256, which gave a total delay in this program of a about two minutes. we can calculate that a count of 2 should give about a one second delay. In practice this is not exactly richt, but it does provide a useful rule of thumb. Let's therefore try settina the D register to 30 instead of 0 (i.e. Edit line 5 to read LD D.30 and see what happens. You should find this gives you a delay of about 10-15 seconds. If you find you need more time to see what shows on the screen in the following proarams then simply increase the initial value in register D. or if you find you are spending too much time waiting for your program to return to the Editor Assembler then iust decrease the value set in D. DO NOT REMOVE PROGRAM I FROM YOUR EDITOR ASSEMBLER! If you do not intend to continue with the following programs now you may wish to save Program I on tape, both for practice In doing this and to avoid having to type it back in next time. The following programs incorporate Program I so as to be able to display their results to the screen. Page 42. Prociram No. 2. This program will write characters to the screen. To do this we first need to know the screen addresses. These can be found in the computer Technical Manual and also in the "Quick Reference Section" at the back of this guide. The VZ memory map shows that memory locations 7000H to 7800H (28672 to 29183 decimal) are allocated to Video Display Ram. The actual screen addresses however only occupy a small portion of this, and are found on the "Video Display Worksheet" provided in the Technical Manual. The actual addresses for display access are from 7000H to 7IFFH. The top line of the screen is accessed by addresses 7000H to 701FH, the second line by 7020H to 703FH, etc. The four addresses surrounding the centre of the screen are 70EFH, 70FOH, 710FH, and 7110H. The bottom line goes from 71EOH to 7IFFH. If you intend doing work which requires accurate screen positioning you should obtain copies of the Video Display Worksheet provided in the Technical Manual or draw up something similar for yourself on graph paper. For our present purposes we really only need to know that anything sent out to an address In the range from 7000H to 7IFFH will be printed on the screen by the Video Interface, or Video Display Processor (VDP). As we intend to write characters to the screen we also need to know the numeric values that correspond to the various characters, bearing in mind that the microprocessor operates entirely with numbers. The VZ uses standard ASCII values for uppercase characters therefore the numeric vlaues can be read directly from an ASCII table. The characters of most inter to us at present are those In the standard alphabet, and in ASCII the upper ca versions of these are assigned values through from 65, for capital A, to 90, f capital 2. N.B. Although the standard ASCII values are used for VZ300 Upper Case characterin the VZ computers do not strictly follow tha ASCII codes therefore it Is better, to avoid confusion, to refer to the ASCII Code Table and Character Code chart provided on pages 203 and 204 of the VZ300 Main Unit Manual (or the equivalent section of the V2200 manual) than to refer to ASCII tables from other sources. However a listing of the main character codes for the VZ300 Is Included in the mouick Reference Section' at the back of this guide for your convenience. Page 43. Beginning with the final version of Program I (11 lines) Insert the following lines after line 2, i.e. immediately after the Call to the clear screen routine and before the time delay routine 003 LD BC,7040H 004 LD A,65 005 LD (BC),A The first of the above lines, which should be line 3 in your program, loads the hexadecimal value of the top left-hand corner screen address into the BC register pair. The next line loads the decimal value for the ASCII "All into register A (the Accumulator). The third line instructs the microprocessor to load the value in the Accumulator into the address pointed to by the register pair BC. Provided the remainder of the program '. i.e. from Program 1, is still intact the screen will be cleared before the value for the letter A is loaded to the screen address, and the time delay will hold the resultant display on the screen long enough for it to be seen. (The VDP actually keeps the character on the screen, once written, which is why the B and C registers can be re-used for the time delay which prevents too early a return to the Editor Assembler). Once you have inserted these lines correctly you can set the Origin, Assemble the program, and if it assembles error free Run it. You should see an A In the top left-hand corner of the screen for whatever length of time you have set up with the time delay. Once you have the correct display you should use the Edit command to chance the values entered into resister A and the BC register pair. Remember that the only valid screen addresses, and therefore the only numbers that should be entered into the BC pair to achieve an output to the screen, are between 7000H and 71FFH. If you want alphabetical characters you should put numbers between 65 and 90 (decimal) into register A, but you could try anv number between 0 and 255 decimal (00 to FF Hex.) to see what it gives (what is actually displayed will be determined by the VDP; see VZ300 Main Unit Manual p2O4). Numbers larger than 255 are unable to be accepted by register A because it is only an 8 bit register. You should now be able to place any of the available characters anvwhere vou want them to appear on the screen. (You should have noticed by now that if the screen position is not occupied by the Status Line (top line) or the COMMAND Prompt and cursor the characters actually remain until they are scrolled out by new data being written to the screen.. therefore for test programs such as these the delay routine is not really necessary unless the whole screen is required for display. However by startina with this routine installed you have been able to place characters anywhere you liked on the screen without having them overwritten so quickly that they were not seen). Pacie 44. Program No. 3. SimD]e Addition and Subtraction. Now modify your program so that it Is as follows 001 :TEST 013 ADD A.L 002 CLS CALL IC9H 014 LD (BC),A 003 LD BC,7OE8H 015 DLI LD B.0 004 LD H.65 016 LD C.0 005 LD A,H 017 LD D.32 006 LD (BC),A 018 DLY DJNZ DLY 007 LD BC,70FOH 019 DEC C 008 LD L,66 020 JR NZ.DLY 009 LD A,L 021 DEC D oto LD (BC),A 022 JR NZ.DLY Oil LD BC,7OF8H 023 jp 31488 012 LD A,H Lines 3 to 10 of this program place values In the H and L registers. These values are also put out to the screen as characters, but because It is not possible to load from H or L to the memory address pointed to by BC the A register is used to transfer the data. Lines 12 and 13 add the values from H and L and the result of this addition is sent to the screen as a (VZ character or block-graphics) character. Lines 15 to 23 now contain the Delay routine and the Jump back to the Editor Assembler. Once again the values used may change within the limitations already referred to. Try, for example, loading a value of 150 into both H and L. Play around with different values In this program then when you are satisfied with the ADD operation Edit line 13 to read 013 SUB L With this change to line 13 the ADD has now been changed to SUB (note that the two instructions do not take the same form). Once again set the Origin.. Asemble. and Run the program, and try several runs with different values entered Into H and L (and different screen positions If you wish). In these programs addition and subtraction have been used to alter the displayed characters but these operations can be used for arithmetic calculations also. Admittedly the 280 CANNOT Multiply or Divide, but because it can Add, Subtract, and Count this poses no serious problem. To Multiply the programmer simply uses successive additions for the required number of times and similarly division is achieved by havinq the microprocessor count the number of successive subtractions required to bring the original value down to zero. Page 45. Finally, You've Only Just Begun. Finally, you have, In fact. only lust be_qun. As you develop (or otherwise acquire) more machine code routines it is suggested that You keep them stored on tape (or disk if you are fortunate enough to have a disk drive) for ready access when you want to use them. and you may find it useful to add listings of your machine code routines to this guide also. for ready reference when required. I would have liked to provide more "graded examples" of machine code routines in this guide but unfortunately other committments prevent me from putting in the time necessary to do this. so It's over to you. However I hope this at least may have given you an easier introduction to VZ Assembler Programming than I had. 001 :TRY THIS 035 LD (BC).A 002 CLS CALL IC9H 036 INC BC 003 LD BC.7107H 037 LD A.65 004 LD A,72 038 LD (BC).A 005 LD (BC).A 039 INC BC 006 INC BC 040 LD A..77 007 LD A.65 041 LD (BC).A 008 LD (BC).A 042 INC BC 009 INC BC 043 LD A.77 010 LD A.80 044 LD (BC).A oil LD (BC),A 045 INC BC 012 INC BC 046 LD A,73 013 LD A.80 047 LD (BC).A 014 LD (BC).A 048 INC BC 015 INC BC 049 LD A.78 016 LD A,89 050 LD (BC).A 017 LD (BC),A 051 INC BC 018 INC BC 052 LD A.71 019 LD A.96 053 LD (BC)..A 020 LD (BC),A 054 INC BC 021 INC BC 055 LD A.97 022 LD A,80 056 LD (BC) '.A 023 LD (BC).A 057 DLI LD B.0 024 INC BC 058 LD C.0 025 LD A,82 059 LD D..8 026 LD (BC).A 060 DLY DJNZ DLY 027 INC BC 061 DEC C 028 LD A,79 062 JR NZ.DLY 029 LD (BC).A 063 DEC D 030 INC BC 064 JR NZ.DLY 031 LD A.71 065 JP 31488 032 LD (BC).A 033 INC BC Now set Oriain to first free 034 LD Al.82 byte. Assemble. and Run it.